/*
 * =====================================================================================
 *
 *       Filename:  led_button.c
 *
 *    Description:  检测按键，控制LED灯
 *
 *        Version:  1.0
 *        Created:  2018年10月29日 17时15分18秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */

/*
 * 为什么要用unsigned long，而不是unsigned int?
 */
#define GPFCON (*(volatile unsigned long*)0x56000050)
#define GPFDAT (*(volatile unsigned long*)0x56000054)
#define GPGCON (*(volatile unsigned long*)0x56000060)
#define GPGDAT (*(volatile unsigned long*)0x56000064)

#define GPCON_MASK(num) (3<<(num<<1))
#define GPCON_IN(num)   (0<<(num<<1))
#define GPCON_OUT(num)  (1<<(num<<1))
#define GPDAT_HIGH(num) (1<<num)


/*
 * LED0: GPF4
 * LED1: GPF5
 * LED2: GPF6
 *
 * KEY1: GPF0
 * KEY2: GPF2
 * KEY3: GPG3
 */

void delay(unsigned int time)
{
    while(time > 0) {
        time--;
    }
}


int main(int argc, char **argv)
{
    GPFCON &= ~(GPCON_MASK(4));   /* GPIOF_4控制寄存器清零 */
    GPFCON |= GPCON_OUT(4);       /* GPIOF_4控制寄存器设置为:输出模式 */
    GPFCON &= ~(GPCON_MASK(5));   /* GPIOF_5控制寄存器清零 */
    GPFCON |= GPCON_OUT(5);       /* GPIOF_5控制寄存器设置为:输出模式 */
    GPFCON &= ~(GPCON_MASK(6));   /* GPIOF_6控制寄存器清零 */
    GPFCON |= GPCON_OUT(6);       /* GPIOF_6控制寄存器设置为:输出模式 */

    GPFCON &= ~(GPCON_MASK(0));   /* GPIOF_0控制寄存器清零 */
    GPFCON |= GPCON_IN(0);        /* GPIOF_0设置为输入模式 */
    GPFCON &= ~(GPCON_MASK(2));   /* GPIOF_2控制寄存器清零 */
    GPFCON |= GPCON_IN(2);        /* GPIOF_2设置为输入模式 */
    GPGCON &= ~(GPCON_MASK(0));   /* GPIOG_3控制寄存器清零 */
    GPGCON |= GPCON_IN(3);        /* GPIOG_3设置为输入模式 */
    unsigned long input;
    while(1) {
        input = GPFDAT;
        if(input & (1<<0)) {
            GPFDAT |= GPDAT_HIGH(4);
        }
        else {
            GPFDAT &= ~GPDAT_HIGH(4);
        }
        
        if(input & (1<<2)) {
            GPFDAT |= GPDAT_HIGH(5);
        }
        else {
            GPFDAT &= ~GPDAT_HIGH(5);
        }
        input = GPGDAT;
        if(input & (1<<3)) {
            GPFDAT |= GPDAT_HIGH(6);
        }
        else {
            GPFDAT &= ~GPDAT_HIGH(6);
        }
    }
    return 0;
}
